﻿using System;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.CompilerServices;

class Program
{
    public static async Task Main(string[] args)
    {
        // await Task.Run(() => CallerWithAsync());
        await Task.Run(() => CallerWithAwaiter());
        Console.ReadLine();
    }

    static string Greeting(string name)
    {
        TraceThreadAndTask($"running {nameof(Greeting)}");
        Task.Delay(3000).Wait();
        return $"Hello, {name}";
    }

    public static void TraceThreadAndTask(string info)
    {
        string taskInfo = Task.CurrentId == null ? "no task" : "task " +
            Task.CurrentId;

        Console.WriteLine($"{info} in thread {Thread.CurrentThread.ManagedThreadId}" +
            $" and {taskInfo}");
    }

    static Task<string> GreetingAsync(string name) =>
    Task.Run<string>(() =>
    {
        TraceThreadAndTask($"running {nameof(GreetingAsync)}");
        return Greeting(name);
    });

    private async static void CallerWithAsync()
    {
        TraceThreadAndTask($"started {nameof(CallerWithAsync)}");
        string result = await GreetingAsync("Dream");
        Console.WriteLine(result);
        TraceThreadAndTask($"ended {nameof(CallerWithAsync)}");
    }

    private static void CallerWithAwaiter()
    {
        TraceThreadAndTask($"started {nameof(CallerWithAwaiter)}");
        TaskAwaiter<string> awater = GreetingAsync("Dream222").GetAwaiter();
        awater.OnCompleted(onCompleteAwaiter);

        void onCompleteAwaiter()
        {
            Console.WriteLine(awater.GetResult());
            TraceThreadAndTask($"ended {nameof(CallerWithAwaiter)}");
        }
    }
}